<html>
<body>
<form id="form" action="QianDao.php" method="post">
uin(必填): <input id="uin" type="text" name="uin"><br>
skey(必填): <input id="skey" type="text" name="skey"><br>
群号:<input type="text" id="groupId" name="groupId"><br>
（输入一个或不填，为空则签到全部）<br>
<input id="submit" type="submit">
</form>
</body>
</html>
<?php
header("Content-Type: text/html;charset=utf-8");
/*
使用时请修改下面这两个变量,
uin和skey的获取方法如下:
点开QQ上面的 QQ空间, 然后在浏览器里按F12, 并在控制台里执行下面的代码:
    document.cookie.match(/(uin|skey)=(.+?);/g);

然后将显示出来的 uin 和 skey 的值分别赋值到下面这两个变量中, 然后运行这个php,
就会自动在你的所有群里进行签到了.
*/

// $uin = 'o0503722728';//此为本据用请改
// $skey = '@FWjAwr9OF';//处样数使时修:)
// $groupId = '179866367';//签到的群号，为空则签到全部

if($_POST != null){
    $uin = $_POST["uin"];
    $skey = $_POST["skey"];
    $groupId = $_POST["groupId"];
    new QianDao($uin, $skey, $groupId);
}

/****************************
下面的代码一般情况下请不要改动
****************************/

class QianDao{
    private $signUrl = 'https://qun.qq.com/cgi-bin/qiandao/sign/publish';//签到的URL地址

    function __construct($uin, $skey, $groupId){
        $this->un = preg_replace('/^o0*/', '', $uin);//数字QQ号码
        $this->cookie = sprintf('Cookie: uin=%s; skey=%s;', $uin, $skey);//Cookie

        $this->g_tk = $this->getGTK($skey);//计算 g_tk

        $this->sign($this->getQunList($groupId));//获取群列表并签到
    }

    function getGTK($skey){
        $len = strlen($skey);
        $hash = 5381;

        for($i = 0; $i < $len; $i++){
            $hash += ($hash << 5) + ord($skey[$i]);
        }

        return $hash & 0x7fffffff;//计算g_tk
    }

    function getQunList($groupId){
        $html = @file_get_contents(
                sprintf('http://qun.qzone.qq.com/cgi-bin/get_group_list?uin=%s&g_tk=%s', $this->un, $this->g_tk),
                false,
                stream_context_create(array(
                    'http'=>array(
                        'method'=>'GET',
                        'header'=>$this->cookie
                    )
                ))
            );

        preg_match('/(\{[\s\S]+\})/', $html, $qunList);

        if(count($qunList) == 0){
            return NULL;
        }

        $qunList = json_decode($qunList[1]);

        if($qunList == NULL || $qunList->code != 0){
            echo "skey 可能已过期请重新获取";
            return NULL;
        }
        if($groupId != '')
            return $this->findGroup($groupId,$qunList->data->group);
        else
            return $qunList->data->group;
    }

    //在群列表里查找指定群
    function findGroup($groupid,$groups){
      $groupidList = explode(",",$groupid);
      $group = [];
      foreach ($groupidList as $i => $id){
        foreach ($groups as $key => $value) {
            if($value->groupid == $id){
              array_push($group,$value);
            }
          }
      }
      return $group;
    }

    function sign($groups){
        if($groups == NULL)return;

        $i = 1;
        foreach($groups as $qun){
            $this->qiandao($qun->groupid);//签到
            printf("%d\t%s(%d)\tok\r\n", $i++, $qun->groupname, $qun->groupid);//输出群信息
        }
    }

    function qiandao($groupId){
        @file_get_contents($this->signUrl, false,
            stream_context_create(
                array('http' => array(
                    'method'  => 'POST',
                    'header'  => $this->cookie,
                    'content' => sprintf('bkn=%s&template_id=4&gc=%s&client=2&pic_id=&text=今天心情不错', $this->g_tk,$groupId)
                ))
            )
        );
    }
}
?>
